package com.kawins.supers.upload.kind;

import com.kawins.supers.upload.IFileManager;
import com.kawins.supers.upload.core.FileLoadBean;
import com.kawins.supers.upload.core.IFileService;
import com.kawins.util.file.FileUtil;
import com.kawins.util.web.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;

/**
 * @author rankai
 * createTime 2017-10-2017/10/31 14:27
 */
public class KindFileService implements IFileManager {

    private static final Logger log = LoggerFactory.getLogger(KindFileService.class);

    private String realPath = FileUtil.getSeparator();

    private IFileService fileService;

    /**
     * 文件上传的路径,前面不带"/"
     */
    private String mvcResPrefix;

    /**
     * @param file
     * @return
     */
    @Override
    public FileLoadBean upload(MultipartFile file) {
        log.debug("单文件上传");
        return upload(null, file);
    }

    /**
     * @param groupName
     * @param file
     * @return
     */
    @Override
    public FileLoadBean upload(String groupName, MultipartFile file) {
        log.debug("单文件上传 Group >> {} ", groupName);
        if (file == null || file.getSize() == 0) {
            log.warn("上传的文件为空");
            return null;
        }
        String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        String filename = System.currentTimeMillis() + "." + ext;
        groupName = StringUtils.isBlank(groupName) ? UUID.randomUUID().toString() : groupName;
        String filePath = RequestUtil.getRealPath(realPath) + FileUtil.getSeparator() + groupName + FileUtil.getSeparator() + filename;
        FileUtil.upload(filePath, file);
        String urlPath = RequestUtil.getUrlPath();
        String servicePath = StringUtils.isBlank(mvcResPrefix) ?
                urlPath : urlPath + mvcResPrefix;
        FileLoadBean loadBean = new FileLoadBean(servicePath, groupName, filename);
        loadBean.setFileExt(ext);
        loadBean.setFileName(file.getOriginalFilename());
        loadBean.setFileLength(file.getSize());
        if (fileService != null) {
            loadBean.setFileId(fileService.insertFile(loadBean));
        }
        return loadBean;
    }

    @Override
    public FileLoadBean upload(String fileName, String fileExt, byte[] file) {
        return null;
    }

    @Override
    public FileLoadBean upload(String fileName, String fileExt, String groupName, byte[] file) {
        return null;
    }

    /**
     * @param files
     * @return
     */
    @Override
    public List<FileLoadBean> upload(MultipartFile[] files) {
        log.debug("多文件上传");
        if (files == null || files.length == 0) {
            log.warn("上传的文件为空");
            return null;
        }
        List<FileLoadBean> list = new ArrayList<>(files.length);
        UUID uuid = UUID.randomUUID();
        for (MultipartFile file : files) {
            list.add(upload(uuid.toString(), file));
        }
        return list;
    }

    /**
     * @param groupName
     * @param files
     * @return
     */
    @Override
    public List<FileLoadBean> upload(String groupName, MultipartFile[] files) {
        log.debug("多文件上传 Group >> {} ", groupName);
        if (files == null || files.length == 0) {
            log.warn("上传的文件为空");
            return null;
        }
        List<FileLoadBean> list = new ArrayList<>(files.length);
        for (MultipartFile file : files) {
            list.add(upload(groupName, file));
        }
        return list;
    }

    /**
     * @param fileId
     * @return
     */
    @Override
    public ResponseEntity<byte[]> download(Object fileId) {
        log.debug("下载文件");
        if (fileId == null) {
            log.warn("下载的文件ID为空");
            return null;
        }
        FileLoadBean fileLoadBean = fileService.selectFile(fileId);
        if (fileLoadBean != null) {
            String filePath = RequestUtil.getRealPath(realPath) + FileUtil.getSeparator()
                    + fileLoadBean.getGroupName() + FileUtil.getSeparator()
                    + fileLoadBean.getRemoteFileName();
            return download(filePath, fileLoadBean.getFileName());
        }
        log.warn("没有找到对应的文件模型 >> fileId:{}", fileId);
        return null;
    }

    @Override
    public InputStream downloadStream(Object fileId) {
        FileLoadBean fileLoadBean = fileService.selectFile(fileId);
        try {
            String filePath = RequestUtil.getRealPath(realPath) + FileUtil.getSeparator()
                    + fileLoadBean.getGroupName() + FileUtil.getSeparator()
                    + fileLoadBean.getRemoteFileName();
            return new FileInputStream(new File(filePath));
        } catch (FileNotFoundException e) {
            log.warn("not found file, file id is {}", fileLoadBean.getFileId());
        }
        return null;
    }

    /**
     * @param fileId
     * @param file
     * @return
     */
    @Override
    public FileLoadBean update(Object fileId, MultipartFile file) {
        log.debug("更新文件");
        if (fileId == null || file == null) {
            log.warn("传入的就文件ID或将要新上传的文件为空");
            return null;
        }
        delete(fileId);
        return upload(file);
    }

    /**
     * @param fileIds
     * @param files
     * @return
     */
    @Override
    public List<FileLoadBean> update(Set<Object> fileIds, MultipartFile[] files) {
        log.debug("批量更新文件");
        if (fileIds == null || files == null) {
            log.warn("传入的就文件ID或将要新上传的文件为空");
            return null;
        }
        delete(fileIds);
        return upload(files);
    }

    /**
     * @param fileId
     * @param groupName
     * @param file
     * @return
     */
    @Override
    public FileLoadBean update(Object fileId, String groupName, MultipartFile file) {
        log.debug("更新文件");
        if (fileId == null || file == null) {
            log.warn("传入的就文件ID或将要新上传的文件为空");
            return null;
        }
        delete(fileId);
        return upload(groupName, file);
    }

    /**
     * @param fileIds
     * @param groupName
     * @param files
     * @return
     */
    @Override
    public List<FileLoadBean> update(Set<Object> fileIds, String groupName, MultipartFile[] files) {
        log.debug("批量更新文件");
        if (fileIds == null || files == null) {
            log.warn("传入的就文件ID或将要新上传的文件为空");
            return null;
        }
        delete(fileIds);
        return upload(groupName, files);
    }

    /**
     * @param fileId
     * @return
     */
    @Override
    public int delete(Object fileId) {
        log.debug("删除文件");
        FileLoadBean fileLoadBean = fileService.selectFile(fileId);
        if (fileLoadBean != null) {
            String filePath = RequestUtil.getRealPath(realPath) + FileUtil.getSeparator()
                    + fileLoadBean.getGroupName() + FileUtil.getSeparator()
                    + fileLoadBean.getRemoteFileName();
            FileUtil.delAllFile(filePath);
            return 1;
        }
        log.warn("没有找到对应的文件模型 >> fileId:{}", fileId);
        return 0;
    }

    /**
     * @param fileIds
     * @return
     */
    @Override
    public int delete(Set<Object> fileIds) {
        log.debug("批量删除文件");
        if (fileIds == null) {
            log.warn("传入的就文件fileIds为空");
            return 0;
        }
        int n = 0;
        for (Object fileId : fileIds) {
            n += delete(fileId);
        }
        return n;
    }

    /**
     * @param filePath
     * @param specFileName
     * @return
     */
    private ResponseEntity<byte[]> download(String filePath, String specFileName) {
        if (StringUtils.isBlank(filePath) || StringUtils.isBlank(specFileName)) {
            log.warn("下载的文件路径或名称为空 >> filePath:{} specFileName:{}", filePath, specFileName);
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        byte[] content;
        try {
            content = FileUtil.file2Byte(filePath);
            headers.setContentDispositionFormData("attachment",
                    new String(specFileName.getBytes("UTF-8"), "iso-8859-1"));
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            return new ResponseEntity<>(content, headers, HttpStatus.CREATED);
        } catch (Exception e) {
            log.warn("下载的文件失败 >> filePath:{} specFileName:{}", filePath, specFileName);
            e.printStackTrace();
        }
        return null;
    }


    public String getRealPath() {
        return realPath;
    }

    public void setRealPath(String realPath) {
        realPath = realPath.replace("/", FileUtil.getSeparator());
        this.realPath = realPath;
    }

    public IFileService getFileService() {
        return fileService;
    }

    public void setFileService(IFileService fileService) {
        this.fileService = fileService;
    }

    public void setMvcResPrefix(String mvcResPrefix) {
        mvcResPrefix = mvcResPrefix.replace("/", "");
        this.mvcResPrefix = mvcResPrefix + "/";
    }
}
